package top.jfunc.validation.core;

import top.jfunc.validation.annotation.*;
import top.jfunc.validation.utils.NullUtil;
import top.jfunc.validation.utils.ReflectUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * ValidateHandler
 * Created by ZhangGang on 2016/9/27.
 */
public class ValidateHandler {

    public static void notNull(Object value, String msg) {
        try {
            ValidateProcess.notNull(value);
            if (value instanceof String) {
                ValidateProcess.notNull((String) value);
            } else if (value instanceof Number) {
                ValidateProcess.notNull((Number) value);
            } else if (value instanceof Collection) {
                ValidateProcess.notNull((Collection) value);
            } else if (value instanceof Map) {
                ValidateProcess.notNull((Map) value);
            } else if (value instanceof Object[]) {
                ValidateProcess.notNull((Object[]) value);
            }
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void regex(String regex, Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.regex(regex, value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void max(Number max, Object value, String msg) {
        try {
            if (null == value || !(value instanceof Number)) {
                return;
            }
            if (value instanceof Integer) {
                ValidateProcess.max(max.intValue(), (Integer) value);
            } else if (value instanceof Long) {
                ValidateProcess.max(max.longValue(), (Long) value);
            } else if (value instanceof Double) {
                ValidateProcess.max(max.doubleValue(), (Double) value);
            } else if (value instanceof Float) {
                ValidateProcess.max(max.floatValue(), (Float) value);
            } else if (value instanceof Short) {
                ValidateProcess.max(max.shortValue(), (Short) value);
            } else if (value instanceof Byte) {
                ValidateProcess.max(max.byteValue(), (Byte) value);
            }
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void maxLength(int max, Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            if (value instanceof String) {
                ValidateProcess.maxLength(max, (String) value);
            } else if (value instanceof Collection) {
                ValidateProcess.maxLength(max, (Collection) value);
            } else if (value instanceof Map) {
                ValidateProcess.maxLength(max, (Map) value);
            } else if (value instanceof Object[]) {
                ValidateProcess.maxLength(max, (Object[]) value);
            }
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void minLength(int min, Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            if (value instanceof String) {
                ValidateProcess.minLength(min, (String) value);
            } else if (value instanceof Collection) {
                ValidateProcess.minLength(min, (Collection) value);
            } else if (value instanceof Map) {
                ValidateProcess.minLength(min, (Map) value);
            } else if (value instanceof Object[]) {
                ValidateProcess.minLength(min, (Object[]) value);
            }
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }


    public static void min(Number min, Object value, String msg) {
        try {
            if (null == value || !(value instanceof Number)) {
                return;
            }
            if (value instanceof Integer) {
                ValidateProcess.min(min.intValue(), (Integer) value);
            } else if (value instanceof Long) {
                ValidateProcess.min(min.longValue(), (Long) value);
            } else if (value instanceof Double) {
                ValidateProcess.min(min.doubleValue(), (Double) value);
            } else if (value instanceof Float) {
                ValidateProcess.min(min.floatValue(), (Float) value);
            } else if (value instanceof Short) {
                ValidateProcess.min(min.shortValue(), (Short) value);
            } else if (value instanceof Byte) {
                ValidateProcess.min(min.byteValue(), (Byte) value);
            }
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isChinese(Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.isChinese(value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isEnglish(Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.isEnglish(value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isPhone(Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.isPhone(value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isEmail(Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.isEmail(value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isDateMatch(String format, Object value, String msg) {
        try {
            if (null != value) {
                ValidateProcess.isDateMatch(format, value.toString());
            }
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isIdCard(Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.isIdCard(value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void isIp(Object value, String msg) {
        try {
            if (null == value) {
                return;
            }
            ValidateProcess.isIp(value.toString());
        } catch (IllegalArgumentException e) {
            errorMsgHandler(e, msg);
        }
    }

    public static void checkBean(Object value) {
        ValidateHandler.notNull(value , null);
        Class classType = value.getClass();
        Set<Field> fieldSet = ValidateCache.getInstance().getFieldsByClass(classType);
        if (null == fieldSet) {
            fieldSet = ReflectUtil.getFieldsByClass(value.getClass());
            ValidateCache.getInstance().setClassFields(classType, fieldSet);
        }
        if (NullUtil.isNull(fieldSet)) {
            return ;
        }
        for (Field field : fieldSet) {
            Annotation[] annotations = ValidateCache.getInstance().getAnnotationsByField(field);
            if (null == annotations) {
                annotations = field.getAnnotations();
                ValidateCache.getInstance().setFieldAnnotations(field, annotations);
            }
            if (NullUtil.isNull(annotations)) {
                continue ;
            }
            Object fieldValue = ReflectUtil.getFieldValue(value, field);
            for (Annotation annotation : annotations) {
                if (annotation instanceof NotNull) {
                    ValidateHandler.notNull(fieldValue ,((NotNull) annotation).msg());
                } else if (annotation instanceof Max) {
                    Max max = (Max) annotation;
                    ValidateHandler.max(max.value(), fieldValue , max.msg());
                } else if (annotation instanceof Min) {
                    Min min = (Min) annotation;
                    ValidateHandler.min(min.value(), fieldValue , min.msg());
                } else if (annotation instanceof MaxLength) {
                    MaxLength maxLength = (MaxLength) annotation;
                    ValidateHandler.maxLength(maxLength.value(), fieldValue, maxLength.msg());
                } else if (annotation instanceof MinLength) {
                    MinLength minLength = (MinLength) annotation;
                    ValidateHandler.minLength(minLength.value(), fieldValue , minLength.msg());
                } else if (annotation instanceof Email) {
                    ValidateHandler.isEmail(fieldValue , ((Email) annotation).msg());
                } else if (annotation instanceof Phone) {
                    ValidateHandler.isPhone(fieldValue , ((Phone) annotation).msg());
                } else if (annotation instanceof IdCard) {
                    ValidateHandler.isIdCard(fieldValue , ((IdCard) annotation).msg());
                } else if (annotation instanceof Regex) {
                    Regex regex = (Regex) annotation;
                    ValidateHandler.regex(regex.value(), fieldValue , regex.msg());
                } else if (annotation instanceof Date) {
                    Date date = (Date) annotation;
                    String format = date.format();
                    ValidateHandler.isDateMatch(format, fieldValue , date.msg());
                } else if (annotation instanceof Chinese) {
                    ValidateHandler.isChinese(fieldValue , ((Chinese) annotation).msg());
                } else if (annotation instanceof English) {
                    ValidateHandler.isEnglish(fieldValue , ((English) annotation).msg());
                } else if (annotation instanceof IP) {
                    ValidateHandler.isIp(fieldValue , ((IP) annotation).msg());
                }
            }
        }
    }

    private static void errorMsgHandler(IllegalArgumentException e, String msg) {
        if (NullUtil.isNull(msg)) {
            throw e;
        }
        throw new IllegalArgumentException(msg);
    }
}
